//
// Created by 12992 on 24-10-19.
//

// You may need to build the project (run Qt uic code generator) to get "ui_VideoEncodeConfigWidget.h" resolved

#include "videoencodeconfigwidget.h"
#include "ui_VideoEncodeConfigWidget.h"
#include "video_config.hpp"
#include <QRegularExpression>
#include <QRegularExpressionValidator>

namespace gui::widgets
{
    VideoEncodeConfigWidget::VideoEncodeConfigWidget(QWidget* parent) :
            QWidget(parent), ui(new Ui::VideoEncodeConfigWidget)
    {
        ui->setupUi(this);
        this->init_widget();
        this->init_signal();
    }

    VideoEncodeConfigWidget::~VideoEncodeConfigWidget()
    {
        delete ui;
    }

    void VideoEncodeConfigWidget::init_widget() const
    {
        this->ui->maxBitrate->setValidator(
                new QRegularExpressionValidator(QRegularExpression("[0-9]+$"), this->ui->maxBitrate));
        this->ui->avgBitrate->setValidator(
                new QRegularExpressionValidator(QRegularExpression("[0-9]+$"), this->ui->avgBitrate));
        QStringList profileList;
        profileList << "auto" << "baseline" << "main" << "high";
        this->ui->encoderProfile->addItems(profileList);
        QStringList presetList;
        presetList << "auto" << "fast" << "medium" << "slow";
        this->ui->encoderPreset->addItems(presetList);
        QStringList levelList;
        levelList << "auto" << "4" << "4.1" << "4.2" << "5" << "5.1" << "5.2" << "6" << "6.1" << "6.2";
        this->ui->encoderLevel->addItems(levelList);
        QStringList encoderList;
        encoderList << "libx264" << "libx265" << "amf" << "qsv" << "nvcodec";
        this->ui->encoderCombo->addItems(encoderList);
        QStringList framerateList;
        framerateList << "25" << "30" << "60";
        this->ui->framerateCombo->addItems(framerateList);
        this->ui->framerateCombo->setCurrentIndex(1);

        QStringList resolutionList;
        resolutionList << "1080P" << "720P" << "480P" << "360P";
        this->ui->resolutionCombo->addItems(resolutionList);
    }

    void VideoEncodeConfigWidget::init_signal()
    {
        connect(this->ui->copyStream, &QCheckBox::checkStateChanged,
                this, &VideoEncodeConfigWidget::changeCopyStream);
        connect(this->ui->CBRButton, &QRadioButton::toggled,
                this, &VideoEncodeConfigWidget::changeCBR);
    }

    void VideoEncodeConfigWidget::changeCopyStream(Qt::CheckState currState)
    {
        switch (currState)
        {
            case Qt::CheckState::Unchecked:this->ui->widget_17->setEnabled(true);
                break;
            default:this->ui->widget_17->setDisabled(true);
        }
    }


    void VideoEncodeConfigWidget::setConfig(const utils::video_config& config)
    {
        QVector<QComboBox*> vecCombo =
                {
                        this->ui->encoderCombo,
                        this->ui->framerateCombo,
                        this->ui->encoderPreset,
                        this->ui->encoderProfile,
                        this->ui->encoderLevel
                };
        QVector<QString> vecString =
                {
                        QString::fromStdString(config.get_encoder()),
                        QString::number(config.get_framerate()),
                        QString::fromStdString(config.get_preset()),
                        QString::fromStdString(config.get_profile()),
                        QString::fromStdString(config.get_level())
                };
        for (int i = 0; i < vecCombo.size(); i++)
        {
            int index = vecCombo.at(i)->findText(vecString.at(i));
            index = (index == -1) ? 0 : index;
            vecCombo.at(i)->setCurrentIndex(index);
        }
        if (config.get_bit_control() == utils::video_config::bit_control::CBR)
        {
            this->ui->CBRButton->setChecked(true);
        }
        else
        {
            this->ui->VBRButton->setChecked(true);
            this->ui->avgBitrate->setText(QString::number(config.get_max_bitrate()));
        }
        this->ui->avgBitrate->setText(QString::number(config.get_bitrate()));
    }

    void VideoEncodeConfigWidget::changeCBR()
    {
        if (this->ui->CBRButton->isChecked())
        {
            this->ui->maxBitrate->setDisabled(true);
        }
        else
        {
            this->ui->maxBitrate->setEnabled(true);
        }
    }

    std::pair<int, int> str_to_resolution(const QString& str)
    {
        if (str == "360P")
        {
            return {480, 360};
        }
        else if (str == "480")
        {
            return {640, 480};
        }
        else if (str == "720P")
        {
            return {1280, 720};
        }
        else
        {
            return {1920, 1080};
        }
    }

    utils::video_config VideoEncodeConfigWidget::getVideoConfig() const
    {
        using namespace std;
        auto encoder = this->ui->encoderCombo->currentText().toStdString();
        int framerate = this->ui->framerateCombo->currentText().toInt();
        auto preset = this->ui->encoderPreset->currentText().toStdString();
        auto profile = this->ui->encoderProfile->currentText().toStdString();
        auto level = this->ui->encoderLevel->currentText().toStdString();
        int avgBitrate = this->ui->avgBitrate->text().toInt();
        auto [width, height] = str_to_resolution(this->ui->resolutionCombo->currentText());
        // TODO avgBitrate 错误处理
        if (this->ui->CBRButton->isChecked())
        {
            return utils::video_config::cbr_config(
                    encoder, profile, level, preset, width, height, framerate, avgBitrate
            );
        }
        else
        {
            // TODO maxBitrate 错误处理
            int maxBitrate = this->ui->maxBitrate->text().toInt();
            return utils::video_config::vbr_config(
                    encoder, profile, level, preset, width, height, framerate, avgBitrate, maxBitrate, 0
            );
        }
    }
} // gui::widgets
